package com.lee.auth.endpoint;

import com.lee.common.exception.CustomException;
import com.lee.common.exception.FailureStatus;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * @author Lee HN
 * @date 2021/4/12 18:51
 */
@Component
public class ClientHolder {

    private static final CustomException InvalidClient = new CustomException(FailureStatus.INVALID_CREDENTIAL, "Invalid client");

    private static final String AUTH_HEADER = "Authorization";

    private static final String CLIENT_PREFIX = "Basic ";

    private static final ClientInfo[] ClientInfos = {
            ClientInfo.of("lee-app", "123456", 180 * 1000),
            ClientInfo.of("lee-web", "123456", 180 * 1000),
            ClientInfo.of("lee-super", "123456", 60 * 60 * 24 * 1000)};

    public final ClientInfo obtainClientDetails(HttpServletRequest request) {

        String header = request.getHeader(AUTH_HEADER);

        if (header == null || !header.startsWith(CLIENT_PREFIX))
            throw InvalidClient;

        byte[] base64Token = header.substring(CLIENT_PREFIX.length()).getBytes(UTF_8);
        byte[] decoded;
        try {
            decoded = Base64.getDecoder().decode(base64Token);
        } catch (IllegalArgumentException e) {
            throw InvalidClient;
        }

        String token = new String(decoded, UTF_8);

        int index = token.indexOf(":");

        if (index == -1)
            throw InvalidClient;

        String clientId = token.substring(0, index);
        String clientSecret = token.substring(index + 1);

        ClientInfo clientInfo = null;
        for (ClientInfo c : ClientInfos)
            if (c.id.equals(clientId) && c.secret.equals(clientSecret))
                clientInfo = c;

        if (clientInfo == null)
            throw InvalidClient;

        return clientInfo;

    }

    public final ClientInfo obtainClientDetails(String clientId) {

        ClientInfo clientInfo = null;
        for (ClientInfo c : ClientInfos)
            if (c.id.equals(clientId))
                clientInfo = c;

        if (clientInfo == null)
            throw InvalidClient;

        return clientInfo;

    }

    @AllArgsConstructor(staticName = "of")
    public static class ClientInfo {

        public String id;

        public String secret;

        public long validity;

    }

}
